package com.qf.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qf.commom.minio.utils.MinioUtil;
import com.qf.common.MinioCommon;
import com.qf.entity.user.User;
import com.qf.enums.RedisKeyEnum;
import com.qf.mapper.UserMapper;
import com.qf.param.LoginParam;
import com.qf.param.RegisterParam;
import com.qf.param.UserParam;
import com.qf.redis.RedisUtil;
import com.qf.service.UserService;
import com.qf.util.JwtUtils;
import com.qf.util.TokenUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * --- 万物归集  不随你我 ---
 * <p>
 * 快捷短语
 * main ==  public static void main(String[] args);
 * sout ==  System.out.println();
 *
 * @author shuhan
 * @date 2025/6/9
 * @desc
 */
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private MinioUtil minioUtil;

    // 登录
    @Override
    public String login(LoginParam loginParam) {

        if (loginParam == null){
            throw new RuntimeException("请输入用户名和密码...");
        }
        User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
                    .eq(User::getUserName, loginParam.getUserName()));
        if (user == null) {
            throw new RuntimeException("用户名错误");
        }
        if (!user.getPassword().equals(loginParam.getPassword())) {
            throw new RuntimeException("密码错误");
        }

        HashMap<String, Object> map = new HashMap<>();
        map.put("uid", user.getId());
        String token = JwtUtils.createJwt(map);

        return token;
    }

    // 注册
    @Override
    public void register(RegisterParam registerParam) {
        // 判空
        if (registerParam == null){
            throw new RuntimeException("请输入用户名、密码、手机号、邮箱...");
        }

        // 判用户名或手机号或邮箱是否已经存在
        User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
                    .eq(User::getUserName, registerParam.getUserName())
                    .or()
                    .eq(User::getPhone, registerParam.getPhone())
                    .or()
                    .eq(User::getEmail, registerParam.getEmail()));
        if (user != null) {
            throw new RuntimeException("用户名或手机号或邮箱已经存在");
        }

        // 判断验证码是否正确
        String code = redisUtil.getCacheObject(RedisKeyEnum.KEY_CODE.getKey() + registerParam.getPhone());
        if(code.isEmpty() && !code.equals(registerParam.getCode())){
            throw new RuntimeException("验证码错误");
        }

        // 注册成功
        User lastuser = new User();
        // 将注册参数复制到User对象中
        BeanUtils.copyProperties(registerParam, lastuser);
        // 添加
        userMapper.insert(lastuser);

    }

    // 更新用户信息
    @Override
    public void update(User user) {
        // 判空
        if (user == null) {
            throw new RuntimeException("请输入用户信息...");
        }
        // 通过token获取id
        Integer uid = TokenUtils.getUidFromToken();
        System.out.println("uid = " + uid);

        // 判断用户是否存在
        User oldUser = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
                .eq(User::getId, uid));
        if (oldUser == null) {
            throw new RuntimeException("用户不存在");
        }

        // 更新
        userMapper.update(user, Wrappers.lambdaUpdate(User.class)
                .eq(User::getId, uid));

    }

    // 更新并上传头像
    @Override
    public String updateAvatar(MultipartFile file) {

        // 获取并生成头像文件名
        String filename = file.getOriginalFilename();
        String uuid = UUID.randomUUID().toString().replace("-", "");
        filename = uuid + filename.substring(filename.lastIndexOf("."));

        // 上传数据库
        User user = new User();
        user.setId(TokenUtils.getUidFromToken());
        user.setAvatar(MinioCommon.MINIO_START_URL + "/" + filename);
        userMapper.update(user, Wrappers.lambdaUpdate(User.class)
                .eq(User::getId, user.getId()));

        // 上传到minio
        try {
            return minioUtil.upload(filename, file.getInputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void updatePassword(UserParam userParam) {

        if (userParam == null) {
            throw new RuntimeException("请输入用户信息...");
        }
        // 判断旧密码是否正确
        Integer uid = TokenUtils.getUidFromToken();
        User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
                .eq(User::getId, uid));
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        if (!user.getPassword().equals(userParam.getOldPassword())) {
            throw new RuntimeException("旧密码错误");
        }
        // 验证验证码是否正确
        String key = String.format(RedisKeyEnum.KEY_CODE.getKey(), userParam.getPhone());
        System.out.println("key = " + key);
        Integer code = redisUtil.getCacheObject(key);

        if(code == null || !code.equals(userParam.getCode())){
            throw new RuntimeException("验证码错误");
            }
        // 更新密码
        User newUser = new User();
        newUser.setId(uid);
        newUser.setPassword(userParam.getNewPassword());

        userMapper.updateById(newUser);
        // 删除验证码
        redisUtil.deleteObject(key);

    }

    // 生成并发送验证码
    @Override
    public void createCode(String phone) {
        // 验证手机号是否合法
        if (!phone.matches("^1[3-9]\\d{9}$")) {
            throw new RuntimeException("请输入合法的手机号");
        }

        int code = RandomUtil.randomInt(1000,9999);

        String key = String.format(RedisKeyEnum.KEY_CODE.getKey(), phone);
        // 将验证码存储到redis
        redisUtil.setCacheObject(key, code, 600, TimeUnit.SECONDS);

        // 将生成的验证码发送给用户
        // AliSmsUtils.sendSms(SmsEnum.SMS_CODE.getSignName(),
        //         SmsEnum.SMS_CODE.getTemplateCode(),
        //         phone,
        //         String.valueOf(code));

    }

    // 退出登录
    @Override
    public void logout(HttpServletRequest request) {
        // 清除token
        String token = request.getHeader("token");
        // 将token加入黑名单
        redisUtil.setCacheObject(RedisKeyEnum.BLACK_LIST.getKey(), token, 600, TimeUnit.SECONDS);
    }

}
